import {
  Controller,
  Get,
  Res,
  Post,
  Body,
  Req,
  Patch,
  Param,
  Delete,
  BadRequestException,
} from '@nestjs/common';
import { PathItemRelationalService } from './path-item-relational.service';
import { CreatePathItemRelationalDto } from './dto/create-path-item-relational.dto';
import { UpdatePathItemRelationalDto } from './dto/update-path-item-relational.dto';
import { Request } from 'express';
import { PathListService } from '../path-list/path-list.service';
import { CameraRotateService } from '../camera-rotate/camera-rotate.service';
import { AudioService } from '../audio/audio.service';
import { TextService } from '../text/text.service';
import { VideoService } from '../video/video.service';
import { PictureService } from '../picture/picture.service';
import { CameraalongService } from '../cameraalong/cameraalong.service';
import { DynamiclayerService } from '../dynamiclayer/dynamiclayer.service';
import { GeojsonService } from '../geojson/geojson.service';
import { ImagerasterService } from '../imageraster/imageraster.service';
import { MapEaseService } from '../map-ease/map-ease.service';
import { MarkerService } from '../marker/marker.service';
import { ScenePathRelationalService } from '../scene_path_relational/scene_path_relational.service';
import { FileListService } from 'src/file-list/file-list.service';
import { Public } from 'src/common/decorator/public.decorator';
import { PublicResourceService } from 'src/public_resource/public_resource.service';
import { FilmFileRelationalService } from 'src/film_file_relational/film_file_relational.service';
import { FilmPathRelationalService } from 'src/film_path_relational/film_path_relational.service';

@Controller('path-item-relational')
export class PathItemRelationalController {
  constructor(
    private readonly pathItemRelationalService: PathItemRelationalService,
    private readonly pathListService: PathListService,
    private readonly cameraRotateService: CameraRotateService,
    private readonly audioService: AudioService,
    private readonly textService: TextService,
    private readonly videoService: VideoService,
    private readonly pictureService: PictureService,
    private readonly cameraalongService: CameraalongService,
    private readonly dynamiclayerService: DynamiclayerService,
    private readonly geojsonService: GeojsonService,
    private readonly imagerasterService: ImagerasterService,
    private readonly mapEaseService: MapEaseService,
    private readonly markerService: MarkerService,
    private readonly scenePathRelationalService: ScenePathRelationalService,
    private readonly fileListService: FileListService,
    private readonly publicResourceService: PublicResourceService,
    private readonly filmPathRelationalService: FilmPathRelationalService,
  ) {}

  @Post('createRelation')
  async create(
    @Body() createPathItemRelationalDto: CreatePathItemRelationalDto,
  ) {
    try {
      const pathResult = await this.pathListService.findOne(
        createPathItemRelationalDto.path_id,
      );
      let itemResult;
      switch (createPathItemRelationalDto.type) {
        case 'Picture':
          itemResult = await this.pictureService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'Video':
          itemResult = await this.videoService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'Audio':
          itemResult = await this.audioService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'Text':
          itemResult = await this.textService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'CameraRotate':
          itemResult = await this.cameraRotateService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'CameraAlong':
          itemResult = await this.cameraalongService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'DynamicLayer':
          itemResult = await this.dynamiclayerService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'GeoJson':
          itemResult = await this.geojsonService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'ImageRaster':
          itemResult = await this.imagerasterService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'MapEase':
          itemResult = await this.mapEaseService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        case 'Marker':
          itemResult = await this.markerService.findOne(
            createPathItemRelationalDto.item_id,
          );
          break;
        // 可以添加更多类型的处理
        default:
          throw new BadRequestException('Unsupported type');
      }
      // 确保轨道存在，然后创建关系
      if (pathResult && itemResult) {
        await this.pathItemRelationalService.create(
          createPathItemRelationalDto,
        );
        return 'Relation created successfully';
      } else {
        throw new BadRequestException('Invalid path or item id');
      }
    } catch (error) {
      throw new BadRequestException('Failed to create relation');
    }
  }

  @Get()
  findAll() {
    return this.pathItemRelationalService.findAll();
  }

  @Get(':id')
  findOne(@Param('id') id: string) {
    return this.pathItemRelationalService.findOne(id);
  }

  @Get('findItemsBySceneId/:sceneId')
  async findItemsBySceneId(@Param('sceneId') scene_id: string) {
    const pathList =
      await this.scenePathRelationalService.findBySceneId(scene_id);
    const pathIds: string[] = pathList.map((item) => item.path_id);
    const result = await this.pathItemRelationalService.getByPathIds(pathIds);
    const {
      pictureIds,
      videoIds,
      audioIds,
      textIds,
      cameraRotateIds,
      cameraAlongIds,
      dynamiclayerIds,
      geoJsonIds,
      imageRasterIds,
      mapEaseIds,
      markerIds,
    } = result.reduce(
      (acc, item) => {
        if (item.type === 'Picture') {
          acc.pictureIds.push(item.item_id);
        } else if (item.type === 'Video') {
          acc.videoIds.push(item.item_id);
        } else if (item.type === 'Audio') {
          acc.audioIds.push(item.item_id);
        } else if (item.type === 'Text') {
          acc.textIds.push(item.item_id);
        } else if (item.type === 'CameraRotate') {
          acc.cameraRotateIds.push(item.item_id);
        } else if (item.type === 'CameraAlong') {
          acc.cameraAlongIds.push(item.item_id);
        } else if (item.type === 'Dynamiclayer') {
          acc.dynamiclayerIds.push(item.item_id);
        } else if (item.type === 'GeoJson') {
          acc.geoJsonIds.push(item.item_id);
        } else if (item.type === 'ImageRaster') {
          acc.imageRasterIds.push(item.item_id);
        } else if (item.type === 'MapEase') {
          acc.mapEaseIds.push(item.item_id);
        } else if (item.type === 'Marker') {
          acc.markerIds.push(item.item_id);
        } else {
          throw new BadRequestException('Unsupported type');
        }
        return acc;
      },
      {
        pictureIds: [],
        videoIds: [],
        audioIds: [],
        textIds: [],
        cameraRotateIds: [],
        cameraAlongIds: [],
        dynamiclayerIds: [],
        geoJsonIds: [],
        imageRasterIds: [],
        mapEaseIds: [],
        markerIds: [],
      },
    );
    const [
      pictures,
      videos,
      audios,
      texts,
      cameraRotates,
      cameraAlongs,
      dynamicLayers,
      GeoJsons,
      imageRasters,
      mapEases,
      markers,
    ] = await Promise.all([
      this.pictureService.findByIds(pictureIds),
      this.videoService.findByIds(videoIds),
      this.audioService.findByIds(audioIds),
      this.textService.findByIds(textIds),
      this.cameraRotateService.findByIds(cameraRotateIds),
      this.cameraalongService.findByIds(cameraAlongIds),
      this.dynamiclayerService.findByIds(dynamiclayerIds),
      this.geojsonService.findByIds(geoJsonIds),
      this.imagerasterService.findByIds(imageRasterIds),
      this.mapEaseService.findByIds(mapEaseIds),
      this.markerService.findByIds(markerIds),
    ]);
    return {
      pictures,
      videos,
      audios,
      texts,
      cameraRotates,
      cameraAlongs,
      dynamicLayers,
      GeoJsons,
      imageRasters,
      mapEases,
      markers,
    };
  }

  // @Get('findByItemId/:itemId')
  // findByItemId(@Param('itemId') item_id: string) {
  //   return this.pathItemRelationalService.getByItemId(item_id);
  // }

  @Public()
  @Get('findItemsByScenceIdToPath/:sceneId/:type')
  async findItemsByScenceIdToPath(
    @Param('sceneId') sceneId: string,
    @Param('type') type: 'Scene' | 'Film',
  ) {
    let pathList;
    if (type === 'Scene') {
      pathList = await this.scenePathRelationalService.findBySceneId(sceneId);
    } else {
      pathList = await this.filmPathRelationalService.findByFilmId(sceneId);
    }

    const promises = pathList.map(async (pathItem) => {
      return await this.pathItemRelationalService.getByPathId(pathItem.path_id);
    });
    const tempArray = await Promise.all(promises);
    const result = await Promise.all(
      tempArray.map(async (subArray) => {
        return await Promise.all(
          subArray.map(async (item) => {
            let updatedItem, itemTipName;
            switch (item.type) {
              case 'Picture':
                updatedItem = await this.pictureService.findOne(item.item_id);
                itemTipName = await this.getSceneItemTipName(
                  updatedItem,
                  item.type,
                );
                break;
              case 'Video':
                updatedItem = await this.videoService.findOne(item.item_id);
                itemTipName = await this.getSceneItemTipName(
                  updatedItem,
                  item.type,
                );
                break;
              case 'Audio':
                updatedItem = await this.audioService.findOne(item.item_id);
                itemTipName = await this.getSceneItemTipName(
                  updatedItem,
                  item.type,
                );
                break;
              case 'Text':
                updatedItem = await this.textService.findOne(item.item_id);
                itemTipName = updatedItem.content;
                break;
              case 'CameraRotate':
                updatedItem = await this.cameraRotateService.findOne(
                  item.item_id,
                );
                itemTipName = ``;
                break;
              case 'CameraAlong':
                updatedItem = await this.cameraalongService.findOne(
                  item.item_id,
                );
                itemTipName = await this.getSceneItemTipName(
                  updatedItem,
                  item.type,
                );
                break;
              case 'DynamicLayer':
                updatedItem = await this.dynamiclayerService.findOne(
                  item.item_id,
                );
                itemTipName = await this.getSceneItemTipName(
                  updatedItem,
                  item.type,
                );
                break;
              case 'GeoJson':
                updatedItem = await this.geojsonService.findOne(item.item_id);
                itemTipName = await this.getSceneItemTipName(
                  updatedItem,
                  item.type,
                );
                break;
              case 'ImageRaster':
                updatedItem = await this.imagerasterService.findOne(
                  item.item_id,
                );
                itemTipName = await this.getSceneItemTipName(
                  updatedItem,
                  item.type,
                );
                break;
              case 'MapEase':
                updatedItem = await this.mapEaseService.findOne(item.item_id);
                itemTipName = ``;
                break;

              case 'Marker':
                updatedItem = await this.markerService.findOne(item.item_id);
                if (updatedItem.file_id === '') {
                  itemTipName = `未选择Marker背景图片`;
                } else {
                  itemTipName = `${
                    (await this.fileListService.findOne(updatedItem.file_id))
                      .file_name
                  }`;
                }
                break;
            }
            updatedItem.itemType = item.type;
            updatedItem.itemTipName = itemTipName;
            return updatedItem;
          }),
        );
      }),
    );
    return result;
  }

  async getSceneItemTipName(updatedItem: any, type: string) {
    if (updatedItem.resource_type === 'user') {
      return `${
        (await this.fileListService.findOne(updatedItem.file_id)).file_name
      }`;
    } else {
      return `${
        (
          await this.publicResourceService.getPublicResourceById(
            updatedItem.file_id,
          )
        ).file_name
      }`;
    }
  }

  @Patch(':id')
  update(
    @Param('id') id: string,
    @Body() updatePathItemRelationalDto: UpdatePathItemRelationalDto,
  ) {
    return this.pathItemRelationalService.update(
      id,
      updatePathItemRelationalDto,
    );
  }

  @Delete('removePathItemRelationalByItemId/:itemId')
  removePathItemRelationalByItemId(@Param('itemId') itemId: string) {
    return this.pathItemRelationalService.removePathItemRelationalByItemId(
      itemId,
    );
  }

  @Delete(':id')
  remove(@Param('id') id: string) {
    return this.pathItemRelationalService.remove(id);
  }
}
